/**
 * 
 */
package xj.toolkit.ebus.unit;

import java.io.InputStream;

import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.InputStreamResource;

import xj.toolkit.ebus.EventBus;
import xj.toolkit.util.ProxyBuilder;


/**
 * @author hp
 *
 */
public class SpringEventUnitImpl implements EventUnit {

    private UnitSource                	source;
    private	ApplicationContext			root;
    private GenericApplicationContext  	ctx;
    
    /* This subclass of ByteArrayResource attempts to circumvent a bug in
     * org.springframework.core.io.support.PropertiesLoaderSupport.loadProperties()
     * that tries to fetch the filename extension of the properties Resource
     * in an attempt to determine whether to parse the properties as XML or
     * traditional syntax.  ByteArrayResource throws an exception when
     * getFilename() is called because there is no associated filename.
     * This subclass returns a fake filename (without a .xml extension).
     * TODO: Remove this when Spring Framework SPR-5068 gets fixed:
     * http://jira.springframework.org/browse/SPR-5068
     */
    private static class InputStreamResourceHack extends InputStreamResource {
    	public InputStreamResourceHack(InputStream inputStream) {
			super(inputStream);
		}

		public String getFilename() {
	        return "InputStreamResourceHasNoFilename";
		}
    }
    
    public SpringEventUnitImpl(UnitSource source, ApplicationContext root) {
        this.source = source;
        this.root = root;
    }
    
    /* (non-Javadoc)
     * @see com.skymobi.ebus.unit.EventUnit#init(com.skymobi.ebus.EventBus)
     */
//    @Override
    @SuppressWarnings("unchecked")
	public Object init(EventBus eventBus) {
    	
        AbstractApplicationContext topCtx = null;
        
        if ( null != root ) {
        	topCtx = new ClassPathXmlApplicationContext(
        		new String[]{"xj/toolkit/ebus/spring/parentCfg.xml"}, root);
        }
        else {
        	topCtx = new ClassPathXmlApplicationContext("xj/toolkit/ebus/spring/parentCfg.xml");
        }
    
        ProxyBuilder<EventBus> eventBusProxyBuilder = 
        	(ProxyBuilder<EventBus>)topCtx.getBean("eventBusProxyBuilder");
        eventBusProxyBuilder.setImpl(eventBus);
        
        ctx = new GenericApplicationContext(topCtx);
		XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
		xmlReader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_DTD);
		xmlReader.loadBeanDefinitions(new InputStreamResourceHack(source.getInputStream()));
		ctx.refresh();
        
        return ctx;
    }

    /* (non-Javadoc)
     * @see com.skymobi.ebus.unit.EventUnit#destroy(java.lang.Object)
     */
//    @Override
    public void destroy(Object ctx) {
    	if ( null != this.ctx ) {
    		this.ctx.close();
    		this.ctx = null;
    	}
    }

    /* (non-Javadoc)
     * @see com.skymobi.ebus.unit.EventUnit#getDescription()
     */
//    @Override
    public String getDescription() {
        return source.getTemplate();
    }

}
